package auth

import (
	"context"
	"errors"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"google.golang.org/grpc/metadata"
	"net/http"
	"time"
)

var jwtKey = []byte("@#saloud%2")

type Claims struct {
	jwt.StandardClaims
}

/*通过请求头获取claims信息*/
func DecodeClaimsFromRequest(ctx context.Context) (*Claims, error) {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok || len(md.Get("authorization")) == 0 {
		return nil, errors.New("get token error")
	}
	tokenStr := md.Get("authorization")[0]
	token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})
	if err != nil {
		return nil, err
	}

	claims, ok := token.Claims.(*Claims)
	if !ok {
		return nil, errors.New("token claims error")
	}
	return claims, nil
}

/*通过请求头获取claims信息*/
func DecodeClaimsFromGin(c *gin.Context) (*Claims, error) {
	tokenStr := c.GetHeader("authorization")
	token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})
	if err != nil {
		return nil, err
	}

	claims, ok := token.Claims.(*Claims)
	if !ok {
		return nil, errors.New("token claims error")
	}
	return claims, nil
}

func SignToken(name, id, subject string, tokenTimeOut time.Duration) (string, error) {
	claims := &Claims{
		StandardClaims: jwt.StandardClaims{
			Issuer:    name,
			Id:        id,
			Subject:   subject,
			IssuedAt:  time.Now().Unix(),
			ExpiresAt: time.Now().Add(tokenTimeOut).Unix(),
		},
	}
	t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return t.SignedString(jwtKey)
}

/*auth 验证*/
func GinVerify(ctx *gin.Context) {
	tokenStr := ctx.GetHeader("Authorization")
	// 处理直接传入?token=方式获取
	if tokenStr == "" {
		tokenStr = ctx.DefaultQuery("token", "")
	}
	if tokenStr == "" {
		ctx.AbortWithStatus(http.StatusUnauthorized)
		return
	}

	_, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})
	if err != nil {
		ctx.AbortWithStatus(http.StatusUnauthorized)
		return
	}
}
